home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr46 / vfwdk.zip / VFWSDK.ZIP / SAMPLES / BRAVADO / RECT.C < prev    next >
C/C++ Source or Header  |  1993-01-31  |  13KB  |  422 lines

  1. /****************************************************************************
  2.  *
  3.  *   rect.c
  4.  * 
  5.  *   Routines to handle formats, rectangles, and palettes
  6.  *
  7.  *   Microsoft Video for Windows Sample Capture Driver
  8.  *   Chips & Technologies 9001 based frame grabbers.
  9.  *
  10.  *   Copyright (c) 1992-1993 Microsoft Corporation.  All Rights Reserved.
  11.  *
  12.  *    You have a royalty-free right to use, modify, reproduce and 
  13.  *    distribute the Sample Files (and/or any modified version) in 
  14.  *    any way you find useful, provided that you agree that 
  15.  *    Microsoft has no warranty obligations or liability for any 
  16.  *    Sample Application Files which are modified. 
  17.  *
  18.  *   VideoIn channel Definitions:
  19.  *      Source - The overall dimensions of the frame buffer available
  20.  *               for digitizing the image.  
  21.  *      Destination - The requested dimension and format of the image
  22.  *               data.  Since this hardware can only scale the 
  23.  *               image during acquisition, setting the destination
  24.  *               format controls:
  25.  *                 1.  The capture rectangle for incoming video
  26.  *                 2.  The size of the DIB containing the image
  27.  *                 3.  The size of the overlay window
  28.  *
  29.  ***************************************************************************/
  30.  
  31. #include <windows.h>
  32. #include <mmsystem.h>
  33. #include <msvideo.h>
  34. #include <msviddrv.h>
  35. #include "ct.h"
  36.  
  37. #define WIDTHBYTES(i)     ((unsigned)((i+31)&(~31))/8)  /* ULONG aligned ! */
  38.  
  39. /***************************************************************************
  40. ***************************************************************************/
  41.  
  42. /***************************************************************
  43. Convert a single YUV15 to RGB15
  44. R = V * 179/127 + Y
  45. B = U * 226/127 + Y
  46. G = 1.706*Y + .509*R +.194*B
  47.  
  48. Returns:    WORD (RGB15)
  49. ***************************************************************/
  50. extern unsigned char map5to8[];
  51.  
  52. WORD NEAR PASCAL YUV15toRGB15 (int Y, int U, int V)
  53. {
  54.    unsigned char rComp,gComp,bComp;
  55.    int ScaledU, ScaledV, ScaledY;
  56.  
  57.   /* Now scale and form the RGB values */
  58.   ScaledU = MulDiv(U,462,256);  // 229/127 = 1.803
  59.                                 // ((int)((char) (BYTE) U) * 226)/127; 
  60.   ScaledV = MulDiv(V,361,256);  // 179/127 = 1.409
  61.                                 // ((int)((char) (BYTE) V) * 179)/127;
  62.   ScaledY = map5to8[Y >> 3];
  63.   rComp = (unsigned char) max(0, 
  64.               min(255, (int) (ScaledV + ScaledY)));
  65.   bComp = (unsigned char) max(0, 
  66.               min(255, (int) (ScaledU + ScaledY)));
  67.   // G = 1.706 * Y - 0.5094 * R - 0.1942 * B 
  68.   gComp = (unsigned char) max(0, 
  69.               min(255, (int) ((ScaledY * 1747L - rComp * 522L - bComp * 199L) >> 10)));
  70.  
  71.   rComp >>= 3;
  72.   gComp >>= 3;
  73.   bComp >>= 3;
  74.  
  75.   return (WORD) (((gComp & 0x1f) << 5) | ((bComp & 0x1f)) | ((rComp & 0x1f) << 10));
  76. }
  77.  
  78. WORD NEAR PASCAL YUV15toRGB15Unscaled (int Y, int U, int V)
  79. {
  80.   unsigned char rComp,gComp,bComp;
  81.   int ScaledU, ScaledV, ScaledY;
  82.  
  83.   ScaledY = Y;
  84.   ScaledU = U;
  85.   ScaledV = V;
  86.  
  87.   rComp = (unsigned char) max(0, 
  88.               min(255, (int) (ScaledV + ScaledY)));
  89.   bComp = (unsigned char) max(0, 
  90.               min(255, (int) (ScaledU + ScaledY)));
  91.   // G = 1.706 * Y - 0.5094 * R - 0.1942 * B 
  92.   gComp = (unsigned char) max(0, 
  93.               min(255, (int) ((ScaledY * 1747L - rComp * 522L - bComp * 199L) >> 10)));
  94.  
  95.   rComp >>= 3;
  96.   gComp >>= 3;
  97.   bComp >>= 3;
  98.  
  99.   return (WORD) (((gComp & 0x1f) << 5) | ((bComp & 0x1f)) | ((rComp & 0x1f) << 10));
  100. }
  101.  
  102. /***************************************************************************
  103. ***************************************************************************/
  104.  
  105. DWORD FAR PASCAL GetInSourceRect(LPRECT lprc)
  106. {
  107.     *lprc = grcSourceIn;
  108.     return DV_ERR_OK;
  109. }
  110.  
  111. /***************************************************************************
  112. ***************************************************************************/
  113.  
  114. DWORD FAR PASCAL SetInSourceRect(LPRECT lprc)
  115. {
  116.     //
  117.     //    currently we dont allow the source rect to be set to
  118.     //    anything other than the size of the entire source!
  119.     //
  120.     if (lprc->left   != 0 ||
  121.     lprc->top    != 0 ||
  122.         lprc->right  != (int)(biSource.biWidth - 1) ||
  123.         lprc->bottom != (int)(biSource.biHeight - 1))
  124.  
  125.         return DV_ERR_PARAM1;
  126.  
  127.     grcSourceIn = *lprc;
  128.  
  129.     return DV_ERR_OK;
  130. }
  131.  
  132. /***************************************************************************
  133. ***************************************************************************/
  134.  
  135. DWORD FAR PASCAL GetSourceFormat(LPBITMAPINFOHEADER lpbi, WORD wSize)
  136. {
  137.     if( wSize < sizeof(BITMAPINFOHEADER))
  138.         return DV_ERR_SIZEFIELD;
  139.  
  140.     *lpbi = biSource;
  141.  
  142.     return DV_ERR_OK;
  143. }
  144.  
  145. /***************************************************************************
  146. ***************************************************************************/
  147.  
  148. DWORD FAR PASCAL SetSourceFormat(LPBITMAPINFOHEADER lpbi, WORD wSize)
  149. {
  150.     RECT rc;
  151.     BITMAPINFOHEADER bi;
  152.  
  153.     if (wSize < sizeof(BITMAPINFOHEADER))
  154.         return DV_ERR_SIZEFIELD;
  155.  
  156.     if (lpbi->biSize != sizeof(BITMAPINFOHEADER))
  157.         return DV_ERR_PARAM2;
  158.  
  159.     if (lpbi->biCompression != BI_RGB)
  160.         return DV_ERR_PARAM2;
  161.  
  162.     if (lpbi->biPlanes != 1)
  163.     return DV_ERR_PARAM2;
  164.  
  165.     bi = biSource;
  166.     biSource = *lpbi;
  167.     SetRect(&rc, 0, 0, (int)lpbi->biWidth - 1, (int)lpbi->biHeight - 1);
  168.     SetInSourceRect(&rc);
  169.  
  170.     gwWidthBytesSource = WIDTHBYTES(lpbi->biWidth * lpbi->biBitCount);
  171.     biSource.biSizeImage = gwWidthBytesSource * lpbi->biHeight;
  172.  
  173.     return DV_ERR_OK;
  174. }
  175.  
  176. /***************************************************************************
  177. ***************************************************************************/
  178.  
  179. DWORD FAR PASCAL GetDestFormat(LPBITMAPINFOHEADER lpbi, WORD wSize)
  180. {
  181.     if( wSize < sizeof(BITMAPINFOHEADER))
  182.         return DV_ERR_SIZEFIELD;
  183.  
  184.     *lpbi = biDest;
  185.  
  186.     return DV_ERR_OK;
  187. }
  188.  
  189. /***************************************************************************
  190. ***************************************************************************/
  191.  
  192. // This routine can be called before the CopyBuffer and 
  193. // translation buffers are allocated, so beware!
  194. DWORD FAR PASCAL SetDestFormat(LPBITMAPINFOHEADER lpbi, WORD wSize)
  195. {
  196.     RECT    rc;
  197.     static BOOL fYUVtoRGB16Initialized = FALSE;
  198.  
  199.     if( wSize < sizeof(BITMAPINFOHEADER))
  200.         return DV_ERR_SIZEFIELD;
  201.  
  202.     if( lpbi->biSize != sizeof(BITMAPINFOHEADER))
  203.         return DV_ERR_PARAM2;
  204.  
  205.     if (lpbi->biPlanes != 1)
  206.     return DV_ERR_BADFORMAT;
  207.  
  208.     // Size must be a multiple of 40 and give square pixels
  209.     if ((lpbi->biWidth % 40 != 0) || 
  210.             (lpbi->biHeight != lpbi->biWidth * 3 / 4))
  211.         return DV_ERR_BADFORMAT;
  212.  
  213.     switch (lpbi->biCompression) {
  214.         case BI_RGB:
  215.             switch (lpbi->biBitCount) {
  216.                 case 8:  gwDestFormat = IMAGE_FORMAT_PAL8;  break;
  217.                 case 16: gwDestFormat = IMAGE_FORMAT_RGB16; break;
  218.                 case 24: gwDestFormat = IMAGE_FORMAT_RGB24; break;
  219.                 default:
  220.                     return DV_ERR_BADFORMAT;
  221.             }
  222.             gwWidthBytesDest = WIDTHBYTES(lpbi->biWidth * lpbi->biBitCount);
  223.             break;
  224.  
  225.         case ckidYUV411Packed:
  226.             gwDestFormat = IMAGE_FORMAT_YUV411PACKED;
  227.             gwWidthBytesDest = WIDTHBYTES(lpbi->biWidth * 16);
  228.             break;
  229.  
  230.         case ckidYUV411Unpacked:
  231.             gwDestFormat = IMAGE_FORMAT_YUV411UNPACKED;
  232.             gwWidthBytesDest = WIDTHBYTES(lpbi->biWidth * 16);
  233.             break;
  234.  
  235.         default:
  236.             return DV_ERR_BADFORMAT;
  237.     }
  238.  
  239.     biDest = *lpbi;
  240.     SetRect(&rc, 0, 0, (int)lpbi->biWidth - 1, (int)lpbi->biHeight - 1);
  241.     SetInDestRect(&rc);
  242.     CT_SetDisplayRect (&rc);
  243.         
  244.     biDest.biSizeImage = gwWidthBytesDest * lpbi->biHeight;
  245.  
  246.     // Commonly used globals (should reference biDest instead)
  247.     gwWidth = (WORD) biDest.biWidth;
  248.     gwHeight = (WORD) biDest.biHeight;
  249.     gwSize40 = gwWidth / 40;
  250.  
  251.     // Allocate an extra copy buffer for smooth Overlays
  252.     // This buffer may not be required in other implementations.
  253.  
  254.     if (fpCopyBuffer) {
  255.         GlobalFree(HIWORD(fpCopyBuffer));
  256.         
  257.         fpCopyBuffer = GlobalLock(GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE, 
  258.                 (DWORD) gwWidth * (DWORD) gwHeight * 2L));
  259.  
  260.         if (fpCopyBuffer == NULL)
  261.             return DV_ERR_NOMEM;
  262.     }
  263.  
  264.     //
  265.     //  When converting to 16bit DIB format, calc an XLATE table
  266.     //  the first time through this loop
  267.     //
  268.     if (fpYUVtoRGB16) {
  269.         if ((gwDestFormat == IMAGE_FORMAT_RGB16) && !fYUVtoRGB16Initialized) {
  270.             WORD w;
  271.             int y, u, v;
  272.  
  273.             fYUVtoRGB16Initialized = TRUE;
  274.  
  275.             w = 0;
  276.             for (y = 0; y <= 255; y += 8) {
  277.                 for (u = 0; u <= 255; u += 8) {      // center bucket
  278.                     for (v = 0; v <= 255; v += 8) {
  279.                         // w is the equivalent RGB value
  280.                         fpYUVtoRGB16[w++] = YUV15toRGB15 (y, (int)(char)(BYTE) u, (int)(char)(BYTE)v);
  281.                     }
  282.                 }
  283.             }
  284.         }
  285.     }
  286.     return DV_ERR_OK;
  287. }
  288.  
  289. /***************************************************************************
  290. ***************************************************************************/
  291.  
  292. DWORD FAR PASCAL GetInDestRect(LPRECT lprc)
  293. {
  294.     *lprc = grcDestIn;
  295.  
  296.     return DV_ERR_OK;
  297. }
  298.  
  299. /***************************************************************************
  300. ***************************************************************************/
  301.  
  302. DWORD FAR PASCAL SetInDestRect(LPRECT lprc)
  303. {
  304.     //
  305.     //  currently we dont allow the dest rect to be set to
  306.     //  anything other than the size of the entire dest!
  307.     //
  308.     if (lprc->left   != 0 ||
  309.     lprc->top    != 0 ||
  310.         lprc->right  != (int)(biDest.biWidth-1) ||
  311.         lprc->bottom != (int)(biDest.biHeight-1))
  312.  
  313.         return DV_ERR_PARAM1;
  314.  
  315.     grcDestIn = *lprc;
  316.  
  317.     return DV_ERR_OK;
  318. }
  319.  
  320. /***************************************************************************
  321.  
  322. ***************************************************************************/
  323. // What portion of the frame buffer do we want to display?
  324. DWORD FAR PASCAL SetExtOutSourceRect(LPRECT lprc)
  325. {
  326.     grcSourceExtOut = *lprc;
  327.  
  328.     //
  329.     //  This defines the pan and scroll of the overlay
  330.     //
  331.  
  332.     CT_SetPanAndScroll (lprc);
  333.  
  334.     return DV_ERR_OK;
  335. }
  336.  
  337. /***************************************************************************
  338. ***************************************************************************/
  339. // Where (in Windows screen coords) is the overlay to appear?
  340. DWORD FAR PASCAL SetExtOutDestRect(LPRECT lprc)
  341. {
  342.     grcDestExtOut = *lprc;
  343.  
  344.     return DV_ERR_OK;
  345. }
  346.  
  347. /***************************************************************************
  348.  
  349.  
  350.  
  351.  
  352.  
  353.  
  354.  
  355. /***************************************************************************
  356. ***************************************************************************/
  357.  
  358. DWORD FAR PASCAL GetDestPalette(LPLOGPALETTE lppal, WORD wSize)
  359. {
  360.     int i;
  361.  
  362.     if(wSize < sizeof(LOGPALETTE) +
  363.         (palCurrent.palNumEntries-1) * sizeof(PALETTEENTRY)) {
  364.         return DV_ERR_SIZEFIELD;
  365.     }
  366.  
  367.     /* copy the palette */
  368.  
  369.     lppal->palVersion    = palCurrent.palVersion;
  370.     lppal->palNumEntries = palCurrent.palNumEntries;
  371.  
  372.     for (i=0; i < (int)palCurrent.palNumEntries; i++)
  373.         lppal->palPalEntry[i] = palCurrent.palPalEntry[i];
  374.  
  375.     return DV_ERR_OK;
  376. }
  377.  
  378.  
  379. /***************************************************************************
  380. ***************************************************************************/
  381.  
  382. DWORD FAR PASCAL SetDestPalette(LPLOGPALETTE lppal, LPBYTE lpXlat)
  383. {
  384.     HPALETTE hpal;
  385.     WORD w;
  386.     DWORD dwReturn = DV_ERR_OK;
  387.  
  388.     palCurrent.palVersion     = lppal->palVersion;
  389.     palCurrent.palNumEntries  = lppal->palNumEntries;
  390.  
  391.     for (w=0; w<palCurrent.palNumEntries; w++)
  392.         palCurrent.palPalEntry[w] = lppal->palPalEntry[w];
  393.  
  394.     // if passed an RGB15 Xlate table
  395.     if (lpXlat) {
  396.         int y, u, v;
  397.         WORD wRGB15;
  398.  
  399.         // We've been given an RGB15 Xlate table.
  400.         // Use this to create a YUV15 Xlate table.
  401.  
  402.         w = 0;
  403.         for (y = 0; y <= 255; y += 8) {
  404.             for (u = 0; u <= 255; u += 8) {      // center bucket
  405.                 for (v = 0; v <= 255; v += 8) {
  406.                     wRGB15 = YUV15toRGB15 (y, (int)(char)(BYTE) u, (int)(char)(BYTE)v);
  407.                     // w is the equivalent RGB value
  408.                     fpTrans16to8[w++] = *(lpXlat + wRGB15);
  409.                 }
  410.             }
  411.         }
  412.     } // endif lpXlate
  413.     else if (hpal = CreatePalette(lppal)) {
  414.         TransRecalcPal(hpal);
  415.         DeleteObject(hpal);
  416.     } else {
  417.         dwReturn = DV_ERR_CREATEPALETTE;
  418.     }
  419.     return dwReturn;
  420. }
  421.  
  422.